/*************************************************************************
	> File Name: iterator.h
	> Author: ma6174
	> Mail: ma6174@163.com 
	> Created Time: 2021年12月03日 星期五 19时33分02秒
 ************************************************************************/

#include<iostream>
#include <string>
#include <vector>

class Iterator
{
public:
	virtual std::string first() = 0;
	virtual std::string next() = 0;
	virtual bool isDone() = 0;
	virtual std::string currentItem() = 0;
};

class Aggregate
{
public:
	virtual Iterator* createIterator() = 0;
	virtual int count() = 0;
	virtual std::string operator[](int index) = 0;
	virtual void append(std::string s) = 0;
};

class ConcreteIterator : public Iterator
{
public:
	ConcreteIterator(Aggregate* a) : aggregate(a) {}

	virtual std::string first();

	virtual std::string next();

	virtual bool isDone();

	virtual std::string currentItem();

private:
	Aggregate* aggregate;
	int current = 0;
};

class ConcreteIteratorDesc : public Iterator
{
public:
	ConcreteIteratorDesc(Aggregate* a, int index) : aggregate(a), current(index) {}

	virtual std::string first();

	virtual std::string next();

	virtual bool isDone();

	virtual std::string currentItem();

private:
	Aggregate* aggregate;
	int current;
};

class ConcreteAggregate : public Aggregate
{
public:
	virtual Iterator* createIterator()
	{
		return new ConcreteIterator(this);
	}

	virtual int count()
	{
		return items.size();
	}

	virtual std::string operator[](int index)
	{
		return items[index];
	}

	virtual void append(std::string s)
	{
		items.push_back(s);
	}

private:
	std::vector<std::string> items;
};


//ConcreteIterator实现部分
std::string ConcreteIterator::first()
{
	return (*aggregate)[0];
}

std::string ConcreteIterator::next()
{
	++current;
	std::string ret;
	if (current < aggregate->count())
		ret = (*aggregate)[current];
	return ret;
}

bool ConcreteIterator::isDone()
{
	return current >= aggregate->count() ? true : false;
}

std::string ConcreteIterator::currentItem()
{
	return (*aggregate)[current];
}

//ConcreteIteratorDesc实现部分
std::string ConcreteIteratorDesc::first()
{
	return (*aggregate)[aggregate->count() - 1];
}

std::string ConcreteIteratorDesc::next()
{
	--current;
	std::string ret;
	if (current >= 0)
		ret = (*aggregate)[current];
	return ret;
}

bool ConcreteIteratorDesc::isDone()
{
	return current < 0 ? true : false;
}

std::string ConcreteIteratorDesc::currentItem()
{
	return (*aggregate)[current];
}
